List Utilities by Zed Lopez

Version 1/220327

"List utility functions"
Jump to extension code
Jump to "List tests" example
Copy Include List Utilities by Zed Lopez to clipboard Include List Utilities by Zed Lopez.
Chapter Examples

Example: ** List tests

Copy "List tests" to clipboard
"List tests"
Include List Utilities by Zed Lopez.
Include Unit Tests by Zed Lopez.

Use test automatically.

Lab is a room.

emptying is a unit test. "Emptying".

empty-l is a list of numbers that varies.
empty-l is usually {}.
ref is always { 0, 1, 2 }.
rev-ref is always { 2, 1, 0 }.
lol is always { { 0, 1, 2 }, { 0, 2, 1 }, { 1, 0, 2 }, { 1, 2, 0 }, { 2, 0, 1 }, { 2, 1, 0 } }.
list9 is always { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.
loneliest is always { 1 }.
teens is always { 13, 14, 15, 16, 17, 18, 19 }.

For testing emptying:
     let L be a list of numbers;
     empty L;
     for "emptying an empty list" assert L is empty;
     let L2 be { 1, 2, 3 };
     empty L2;
     for "emptying a non-empty list" assert the number of entries in L2 is 0;

Random entry is a unit test. "Random entry"

test-num is initially 0.

For testing random entry:
   let z be a random entry from empty-l;
   for "random entry from empty list" assert z is 0;
   for "random entry from empty list error" assert "[test random entry from empty-l is 0]" reports an error;
   let z2 be a random entry from empty-l or improbable number;
   for "random entry from empty list or backup" assert z2 is improbable number;
   let count be { 0, 0, 0 };
   repeat with i running from 1 to 300 begin;
     let x be a random entry in ref;
     increment entry (x + 1) in count;
   end repeat;
   let label be "monte carlo [count]";
   repeat with i running through ref begin;
     let j be i + 1;
     if entry j in count < 50 or entry j in count > 200 begin;
       for label fail;
       rule fails;
     end if;
   end repeat;
   for label pass;

Shuffle is a unit test. "Returning shuffled list".

For testing shuffle:
   let empty-shuffling be shuffled empty-l;
   for "empty list shuffled" assert empty-shuffling is empty;
   let count be a list of numbers;
   let indices be { 6, 8, 12, 16, 20, 22 }; [ the trinary values of combinations of 0, 1, 2 ]
   extend count to 22 entries;
   let result be a list of numbers;
   let orig be { 0, 1, 2};
   repeat with i running from 1 to 300 begin;
     let M be shuffled ref;
     let val be 1 + (entry 1 of M) + ((entry 2 of M) * 3) + ((entry 3 of M) * 9); [ convert to a trinary val ]
     now entry val of count is (entry val of count) + 1;
   end repeat;
   repeat with i running through indices begin;
     add entry i of count to result;
   end repeat;
   for "Original unchanged" assert orig is {0, 1, 2};
   let label be "Shuffle [result]";
   [ the mean is 42.66 ]
   repeat with i running through result begin;
     if i < 22 or i > 86 begin;
       for label fail;
       rule fails;
     end if;
   end repeat;
   for label pass;

Sort is a unit test.

For testing sort:
   let empty-sorted be sorted empty-l;
   for "empty list sorted" assert empty-sorted is empty;
   for "empty list sorted backwards" assert sorted empty-l backwards is empty;
   repeat with l running through lol begin;
     let orig be l;
     for "sort [l]" assert sorted l is ref;
     unless l is orig, for "sort [l] original changed" fail;
     for "sort [l] backwards" assert sorted l backwards is rev-ref;
   end repeat;

Reverse is a unit test. "Returning reversed list".

For testing reverse:
   let empty-reverse be reverse empty-l;
   for "empty list reverse" assert empty-reverse is empty;
   repeat with l running through lol begin;
     let orig be l;
     let r be reverse l;
     let len be number of entries in l;
     repeat with i running from 1 to len begin;
       unless entry i of r is entry (len + 1 - i) of l begin;
         for "sort [r] backwards" fail;
         rule fails;
       end unless;
     end repeat;
   end repeat;
   for "sort backwards" pass;

Pop value is a unit test. "Pop value".

For testing pop value:
   let l1 be ref;
   let p be pop l1;
   for "popped value { 0, 1, 2 }, got 2" assert p is 2;
   for "popped value { 0, 1, 2 }, length of list" assert number of entries in l1 is 2;
   for "popped value { 0, 1, 2 }, first entry 0" assert entry 1 of l1 is 0;
   for "popped value { 0, 1, 2 }, second entry 1" assert entry 2 of l1 is 1;
   for "popped non-empty with backup" assert pop l1 or improbable number is 1;
   let l2 be a list of numbers;
   for "popped value empty list" assert pop l2 is 0;
   for "popped value empty list error" assert "[test pop l2 is 0]" reports error;
   let l3 be teens;
   for "popped value non-empty with backup" assert pop l3 or improbable number is 19;
   let l4 be a list of numbers;
   for "popped value empty with backup" assert pop l4 or improbable number is improbable number;
  
Pop discarding is a unit test. "Pop, discarding value".

empty-num-list is a list of numbers that varies.
empty-num-list is initially {}.

For testing pop discarding:
   let l1 be ref;
   pop l1;
   for "popped { 0, 1, 2 }, length of list" assert number of entries in l1 is 2;
   for "popped { 0, 1, 2 }, first entry" assert entry 1 of l1 is 0;
   for "popped { 0, 1, 2 }, second entry" assert entry 2 of l1 is 1;
   for "popped empty list error" assert "[test pop empty-num-list]" reports error;
   let l2 be a list of numbers;
   pop l2;
   for "popped empty list" assert l2 is empty;

Push is a unit test. "Push".
  
For testing push:
   let l1 be ref;
   push 5 on l1;
   for "pushed 5 on { 0, 1, 2 }, length of list" assert number of entries in l1 is 4;
   for "pushed 5 on { 0, 1, 2 }, first entry" assert entry 1 of l1 is 0;
   for "pushed 5 on { 0, 1, 2 }, third entry" assert entry 3 of l1 is 2;
   for "pushed 5 on { 0, 1, 2 }, fourth entry" assert entry 4 of l1 is 5;
   let l2 be a list of numbers;
   push 7 on l2;
   for "push 7 on {}, length of list" assert number of entries in l2 is 1;
   for "push 7 on {}, sole entry" assert entry 1 of l2 is 7;

Shift value is a unit test. "Shift value".

For testing shift value:
   let l1 be ref;
   let l2 be l1;
   let p be shift l2;
   for "shift value { 0, 1, 2 }, got 0" assert p is 0;
   for "shift value { 0, 1, 2 }, length of list" assert number of entries in l2 is 2;
   for "shift value { 0, 1, 2 }, first entry" assert entry 1 of l2 is 1;
   for "shift value { 0, 1, 2 }, second entry" assert entry 2 of l2 is 2;
   for "shift value, original unchanged" assert l1 is ref;
   let l2 be teens;
   for "shifted non-empty with backup" assert (shift l2 or improbable number) is 13;
   let L be a list of numbers;
   for "shift value, empty list" assert shift L is 0;
   for "shift value, empty error message" assert "[test shift empty-num-list]" reports error;

  
Shift discarding is a unit test. "Shift, discarding value".

For testing shift discarding:
   let l1 be ref;
   shift l1;
   for "shifted { 0, 1, 2 }, length of list" assert number of entries in l1 is 2;
   for "shifted { 0, 1, 2 }, first entry" assert entry 1 of l1 is 1;
   for "shifted { 0, 1, 2 }, second entry" assert entry 2 of l1 is 2;
   let l2 be a list of numbers;
   shift l2;
   for "shifted empty list" assert l2 is empty; [TODO fails]

Unshift is a unit test. "Unshift".
  
For testing unshift:
   let l1 be ref;
   unshift 5 on l1;
   for "unshifted 5 on { 0, 1, 2 }, length of list" assert number of entries in l1 is 4;
   for "unshifted 5 on { 0, 1, 2 }, first entry" assert entry 1 of l1 is 5;
   for "unshifted 5 on { 0, 1, 2 }, third entry" assert entry 3 of l1 is 1;
   for "unshifted 5 on { 0, 1, 2 }, fourth entry" assert entry 4 of l1 is 2;
   let l2 be a list of numbers;
   unshift 7 on l2;
   for "unshift 7 on {}, length of list" assert number of entries in l2 is 1;
   for "unshift 7 on {}, sole entry" assert entry 1 of l2 is 7;

Last index is a unit test. "Last index."

For testing last index:
   for "empty" assert last index of empty-L is 0;
   for "last of 9" assert last index of list9 is 9;
   for "singleton" assert last index of loneliest is 1;

Last entry is a unit test. "Last entry."

For testing last entry:
   for "empty" assert last entry of empty-l is 0;
   for "last of 9" assert last entry of list9 is 9;
   for "singleton" assert last entry of loneliest is 1;
   for "rev-ref" assert last entry of rev-ref is 0;

Combo is a unit test. "Combination".

For testing combo:
   for "empty and list9" refute empty-l is a combination of list9;
   for "list9 and empty" refute list9 is a combination of empty-l;
   for "ref and rev-ref" assert rev-ref is a combination of ref;
   for "shuffled list9s" assert shuffled list9 is a combination of shuffled list9;


[Backwards slice is a unit test. "Backwards slice".

For testing backwards slice:
for "empty" assert entries 99 to -3 of empty-l is empty;
for "end out of range" assert entries 15 down to 8 of list9 is { 9, 8 };
for "ref" assert entries 3 down to 1 of ref is rev-ref;
for "start out of range" assert entries 4 down to 0 of list9 is { 4, 3, 2, 1 };
for "both out of range" assert entries 15 down to -3 of loneliest is {1};]
  
Uniquity is a unit test. "Uniquity".

For testing uniquity:
   for "empty" assert unique empty-l is empty;
   for "ref" assert sorted unique rev-ref is ref;
   let duplicative be a list of numbers;
   repeat for i in 1 to 3 begin;
     let L be shuffled list9;
     repeat with j running through L begin;
       add j to duplicative;
     end repeat;
   end repeat;
   for "duplicative" assert sorted unique duplicative is list9;
  
Intersection is a unit test. "Intersection".

For testing intersection:
   for "empty 0" assert intersection of empty-l and empty-l is empty;
   for "empty 1" assert intersection of empty-l and list9 is empty;
   for "empty 2" assert intersection of empty-l and loneliest is empty;
   for "empty 3" assert intersection of loneliest and empty-l is empty;
   for "ref and loneliest" assert intersection of ref and loneliest is { 1 };
   for "loneliest and ref" assert intersection of loneliest and ref is { 1 };
   for "rev-ref and loneliest" assert intersection of rev-ref and loneliest is { 1 };
   for "list9 and loneliest" assert intersection of list9 and loneliest is { 1 };
   for "list9 and ref" assert intersection of list9 and ref is { 1, 2 };
   let lista be shuffled list9;
   let listb be shuffled list9;
   let listc be sorted intersection of lista and listb;
   for "shuffled" assert listc is list9;
   for "identical" assert intersection of list9 and list9 is list9;

Sums is a unit test. "Sums".

For testing sums:
   for "empty and ref" assert sum of empty-l and ref is ref;
   for "rev-ref and empty" assert sum of rev-ref and empty-l is rev-ref;
   for "empty and empty" assert sum of empty-l and empty-l is empty;
   for "rev-ref and ref" assert sum of rev-ref and ref is { 2, 1, 0, 0, 1, 2 };
   for "list9 and list9 length" assert size of sum of list9 and list9 is 18;

Union is a unit test. "Union".

For testing union:
   for "ref and rev-ref" assert sorted union of ref and rev-ref is ref;
   for "list9 and ref" assert sorted union of list9 and ref is { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
   for "empty and empty" assert union of empty-l and empty-l is empty;
   for "empty and ref" assert union of empty-l and ref is ref;
   for "loneliest and teens" assert union of loneliest and teens is { 1, 13, 14, 15, 16, 17, 18, 19 };
  
Intersects is a unit test. "if intersects".

For testing intersects:
   for "2 empty lists" refute empty-l intersects empty-l;
   for "empty lists and ref" refute empty-l intersects ref;
   for "teens and list9" refute teens intersects list9;

Disjoint from is a unit test. "if is disjoint from".

For testing disjoint from:
   for "2 empty lists" assert empty-l is disjoint from empty-l;
   for "empty lists and ref" assert empty-l is disjoint from ref;
   for "teens and list9" assert teens is disjoint from list9;


Slice nice is a unit test. "Slice".

For testing slice:
   for "empty" assert entries 3 to 4 of empty-l is empty;
   for "empty error" assert "[test entries 3 to 4 of empty-l is empty]" reports error;
   for "plain" assert entries 2 to 3 of list9 is { 2, 3 };
   for "singleton bottom" assert entries 1 to 1 of list9 is { 1 };
   for "singleton top" assert entries 9 to 9 of list9 is { 9 };
   let test-l be list9;
   for "middle slice" assert entries 3 to 7 of test-l is { 3, 4, 5, 6, 7 };
   for "original unchanged" assert test-l is list9;
   for "start slice" assert entries 1 to 3 of test-l is { 1, 2, 3 };
   for "end slice" assert entries 6 to 9 of test-l is { 6, 7, 8, 9 };
   for "single slice" assert entries 9 to 9 of test-l is { 9 };
   for "singleton" assert entries 1 to 1 of loneliest is { 1 };

End slice is a unit test. "Slice through end"

For testing end slice:
   for "7 of 9" assert entries 7 to last of list9 is { 7, 8, 9 };
   for "singleton" assert entries 1 to last of loneliest is { 1 };
   for "empty" assert entries 1 to 15 of empty-l is empty;
   for "empty reported error" assert "[test entries 1 to 15 of empty-l is empty]" reports error;

Left index is a unit test. "Left index".

For testing left index:
   for "empty-l" assert left index of 5 in empty-l is 0;
   for "empty-l" assert left index of 0 in empty-l is 0;
   for "ref" assert left index of 1 in ref is 2;
   for "teens" assert left index of 15 in teens is 3;
   let l1 be the sum of ref and list9;
   for "sum of ref and list9" assert left index of 1 in l1 is 2;

Rindex is a unit test. "Scooby-doo saying 'windex'".

For testing rindex:
   for "empty-l" assert right index of 5 in empty-l is 0;
   for "empty-l" assert right index of 0 in empty-l is 0;
   for "rindex 1 in ref" assert right index of 1 in ref is 2;
   for "rindex 15 in teens" assert right index of 15 in teens is 3;
   let l1 be the sum of ref and list9;
   for "rindex 8 in sum of ref and list9" assert right index of 8 in l1 is 11;
   for "rindex 1 in sum of ref and list9" assert right index of 1 in l1 is 4;

Zentry is a unit test. "Zentry".

For testing zentry:
   for "empty-l" assert zentry 0 in empty-l is 0;
   for "ref 0" assert zentry 0 in ref is 0;
   for "rev-ref -1" assert zentry -1 in rev-ref is 0;
   for "rev-ref 0th" assert zentry 0 in rev-ref is 2;
   for "teens 2" assert zentry 2 in teens is 15;
   for "teens -2" assert zentry -2 in teens is 18;

Minmax is a unit test. "Min/max".

For testing minmax:
   for "min ref" assert min of ref is 0;
   for "max ref" assert max of ref is 2;
   for "min teens" assert min of teens is 13;
   for "max teens" assert max of teens is 19;
   let L be the shuffled sum of ref and teens;
   for "min L" assert min of ref is 0;
   for "max L" assert max of teens is 19;
Version 1/220327 of List Utilities by Zed Lopez begins here.

"List utility functions"

Chapter empty imperative

To empty a/an/-- (L - a list of values of kind K):
   (- LIST_OF_TY_SetLength({-by-reference:L}, 0); -)

Part sorts

chapter random

[ with empty list, will result in:
*** Couldn't read from entry 1 of a list which is empty ***

*** Run-time problem P50: Attempt to use list item which does not exist.
]

To decide what K is a/-- random entry in/of/from the/a/an/-- (L - a list of values of kind K):
   decide on entry (a random number from 1 to the size of L) in L;

To decide what K is a/-- random entry in/of/from the/a/an/-- (L - a list of values of kind K) or (v - K):
     if L is empty, decide on v;
     decide on entry (a random number from 1 to the size of L) in L;

To decide what list of Ks is a/-- shuffled/randomized (L - a list of values of kind K):
   let M be L;
   sort M in random order;
   decide on M;

chapter sorts
[ modify LIST_OF_TY_Sort to return a value ]

Include (-
Global LIST_OF_TY_Sort_cf;

[ LIST_OF_TY_Sort list dir prop cf i j no_items v;
   BlkMakeMutable(list);
   no_items = BlkValueRead(list, LIST_LENGTH_F);
   if (dir == 2) {
     if (no_items < 2) return list;
     for (i=1:i<no_items:i++) {
       j = random(i+1) - 1;
       v = BlkValueRead(list, LIST_ITEM_BASE+i);
       BlkValueWrite(list, LIST_ITEM_BASE+i, BlkValueRead(list, LIST_ITEM_BASE+j));
       BlkValueWrite(list, LIST_ITEM_BASE+j, v);
     }
     return;
   }
   SetSortDomain(ListSwapEntries, ListCompareEntries);
   if (cf) LIST_OF_TY_Sort_cf = BlkValueCompare;
   else LIST_OF_TY_Sort_cf = 0;
   SortArray(list, prop, dir, no_items, false, 0);
     return list;
];

[ ListSwapEntries list i j v;
   if (i==j) return;
   v = BlkValueRead(list, LIST_ITEM_BASE+i-1);
   BlkValueWrite(list, LIST_ITEM_BASE+i-1, BlkValueRead(list, LIST_ITEM_BASE+j-1));
   BlkValueWrite(list, LIST_ITEM_BASE+j-1, v);
];

[ ListCompareEntries list col i j d cf;
   if (i==j) return 0;
   i = BlkValueRead(list, LIST_ITEM_BASE+i-1);
   j = BlkValueRead(list, LIST_ITEM_BASE+j-1);
   if (I7S_Col) {
     if (i provides I7S_Col) i=i.I7S_Col; else i=0;
     if (j provides I7S_Col) j=j.I7S_Col; else j=0;
     cf = LIST_OF_TY_Sort_cf;
   } else {
     cf = LIST_OF_TY_ComparisonFn(list);
   }
   if (cf == 0) {
     if (i > j) return 1;
     if (i < j) return -1;
     return 0;
   } else
     return cf(i, j);
];

-) instead of "Sorting" in "Lists.i6t".



To decide what list of Ks is a/-- sorted (L - a list of values of kind K):
     (- LIST_OF_TY_Sort({L}, 1) -).

To decide what list of Ks is a/-- sorted (L - a list of values of kind K) in/-- descending/backwards/reverse order/--:
     (- LIST_OF_TY_Sort({L}, -1) -).

chapter reverse

To decide what list of Ks is a/-- reverse of/-- (L - a list of values of kind K):
     (- LIST_OF_TY_Reverse({L},1) -). [ {L} instead of {-lvalue-by-reference:L} ]

Part more flexible prepositions in standard phrases

To remove entry (N - number) in/of/from (L - list of values), if present:
(- LIST_OF_TY_RemoveItemRange({-lvalue-by-reference:L}, {N}, {N}, {phrase options}); -).

To add (LX - list of Ks) at entry (E - number) in/of/to (L - list of values of kind K):
   (- LIST_OF_TY_AppendList({-lvalue-by-reference:L}, {-by-reference:LX}, 1, {E}, 0); -).

To add (new entry - K) at entry (E - number) in/of/to (L - list of values of kind K), if absent:
   (- LIST_OF_TY_InsertItem({-lvalue-by-reference:L}, {new entry}, 1, {E}, {phrase options}); -).

Part stack

Chapter pop

Section pop returning value

Include (-
[ ListPop L kind x last;
last = BlkValueRead(L, LIST_LENGTH_F);
x = LIST_OF_TY_GetItem(L, last);
LIST_OF_TY_RemoveItemRange(L, last, last);
return x;
];
-).

To decide what K is pop of/-- (L - a list of values of kind K):
     (- ListPop({-by-reference:L},{-strong-kind:K}) -).

To decide what K is pop of/-- (L - a list of values of kind K) or (backup - a K):
   if L is empty, decide on backup;
   decide on pop L;

Section pop ignoring value

To pop (L - a list of values of kind K): (- ListPop({-lvalue-by-reference:L}); -).

Chapter push

To push (n - a K) on (L - a list of values of kind K): (- LIST_OF_TY_InsertItem({-lvalue-by-reference:L}, {n}, 0, 0, 0); -).

Part queue

Chapter shift

Section shift returning value

Include (-
[ ListShift L kind x last;
last = BlkValueRead(L, LIST_LENGTH_F);
x = LIST_OF_TY_GetItem(L, 1);
LIST_OF_TY_RemoveItemRange(L, 1, 1);
return x;
];
-).

[if empty, results in:
To decide what K is pop of/-- (L - a list of values of kind K)

*** Couldn't read from entry 1 of a list which is empty ***

*** Run-time problem P50: Attempt to use list item which does not exist.

*** Couldn't remove entries 1 to 1 from the list {}, which has entries in the range 1 to 0 ***
]

To decide what K is shift of/-- (L - a list of values of kind K): (- ListShift({-by-reference:L},{-new:K}) -).

To decide what K is shift of/-- (L - a list of values of kind K) or (backup - a K):
   if L is empty, decide on backup;
   decide on shift L;


Section shift ignoring value

To shift (L - a list of values of kind K): (- ListShift({-by-reference:L}); -).

Chapter Unshift

To unshift (n - a K) on/from (L - a list of values of kind K): (- LIST_OF_TY_InsertItem({-by-reference:L}, {n}, 1 ,1, 0); -).

Book slice

Part slice forward

Chapter slice specified range

To decide what list of K is entries (M - a number) to (N - a number) in/of (L - a list of values of kind K):
     let result be a list of K;
     repeat for i in M to N begin;
       add (entry i in L) to result;
     end repeat;
     if L is empty, decide on L;
     decide on result.

Chapter slice through end

To decide what list of K is entries (M - a number) to end/finish/last of (L - a list of values of kind K):
   decide on entries M to (last index of L) of L.

Part last index/entry

Chapter last index

To decide what number is a/-- last index in/of a/an/-- (L - a list of values of kind K):
     decide on the size of L.

Chapter last entry

To decide what K is a/-- last entry in/of the/a/an/-- (l - a list of values of kind K):
   let x be the number of entries in l;
   if x is zero, decide on null K;
   decide on entry x in l.

Chapter combo

To decide if (L - a list of values of kind K) is a/-- combination of/-- (M - a list of Ks):
   if the size of L is not the size of M, no;
   if sorted L is sorted M, yes;
   no.

Part set functions

To decide which list of values of kind K is a/-- unique (l - a list of values of kind K):
     let r be a list of K;
     repeat with x running through l begin;
       add x to r, if absent;
     end repeat;
     decide on r.

To decide which list of values of kind K is a/-- intersection of (l - a list of values of kind K) and (m - a list of Ks):
     let r be unique l;
     repeat with i running through l begin;
       if i is not listed in m and i is listed in r, remove i from r;
       end repeat;
       decide on r.

To decide which list of values of kind K is a/-- sum of (l - a list of values of kind K) and (m - a list of values of kind M):
     let r be l;
     add m to r;
     decide on r.

To decide which list of values of kind K is a/-- union of (l - a list of values of kind K) and (m - a list of values of kind M):
     decide on the unique sum of l and m.

To decide if (l - a list of values) intersects (m - a list of values):
     if the intersection of l and m is empty, decide no;
     decide yes.

To decide if (l - a list of values) is disjoint from (m - a list of values):
     if the intersection of l and m is empty, decide yes;
     decide no.

To decide what number is a/-- size of (l - a list of values):
     decide on the number of entries in l.

To decide what number is a/-- left/-- index of a/an/-- (x - a value) in a/an/-- (l - a list of values of kind K):
   repeat with i running from 1 to the size of l begin;
     if x is entry i in l, decide on i;
   end repeat;
   decide on 0.

To decide what number is a/-- right index of (x - a value) in (l - a list of values):
   repeat with i running from 1 to size of l begin;
     let idx be 1 + size of l - i;
     if x is entry idx in l, decide on idx;
   end repeat;
   decide on 0.

To decide what number is zentry (n - a number) of/in (L - a list of values of kind K):
   let len be the last index of L;
   if n >= 0 and n < len, decide on entry (n + 1) of L;
   if n < 0 and (0 - n) <= len, decide on entry (len + 1 + n) of L;
   decide on null K;

Include (-
[ listExtreme L k cmp_target cmp i last val result cmp_result;
   if (k) { cmp = KOVComparisonFunction(k); }
   if (k == NUMBER_TY) cmp = utSignedCompare;
last = BlkValueRead(L, LIST_LENGTH_F);
result = LIST_OF_TY_GetItem(L, 1);
for ( i = 2; i <= last; i++ ) {
   val = LIST_OF_TY_GetItem(L, i);
   cmp_result = cmp(val, result);
   if ((cmp_target == 1) && (cmp_result > 0)) result = val;
   else if ((cmp_target == -1) && (cmp_result < 0)) result = val;
}
return result;
];
-)

To decide what K is max/maximum of/-- (L - a list of values of kind K):
   (- listExtreme({L},{-strong-kind:K},1) -)

To decide what K is min/minimum of/-- (L - a list of values of kind K):
   (- listExtreme({L},{-strong-kind:K},-1) -)

Book Central Typecasting-dependent (for use with Central Typecasting by Zed Lopez)

Part ordinalth entry

To decide what K is a/-- (O - an ordinal) entry in/of the/a/an/-- (l - a list of values of kind K):
     decide on entry (O cast as a number) in l.

Volume Descent (for use without Strange Loopiness by Zed Lopez)

To repeat with/for the/a/an/-- (loopvar - nonexisting K variable) running/-- from/in (v - value of kind K) down to (w - K) begin -- end loop:
       (- for ({loopvar}={v}: {loopvar}>={w}: {loopvar}-- ) -).

To repeat with/for the/a/an/-- (loopvar - nonexisting K variable)
   running/-- from/in (v - value of kind K) to (w - K) begin -- end loop
   (documented at ph_repeat):
     (- for ({loopvar}={v}: {loopvar}<={w}: {loopvar}++ ) -).

Volume Central (for use without Central Typecasting by Zed Lopez)

To decide what K is a/-- null (name of kind of value K): (- nothing -)

Volume compare (for use without Unit Tests by Zed Lopez)

Include (-
[ utSignedCompare x y;
if (x > y) return 1;
if (x < y) return -1;
return 0;
];
-);

List Utilities ends here.